using AdmissionQA.Application.Common;
using AdmissionQA.Application.Dtos.AdmissionPolicy;
using AdmissionQA.Application.ServiceInterfaces;
using AdmissionQA.Domain.Entities;
using AdmissionQA.Domain.Repositorys;
using Microsoft.Extensions.Logging;

namespace AdmissionQA.Application.Services;

/// <summary>
/// 招生政策服务实现
/// </summary>
public class AdmissionPolicyServices(IRepository<AdmissionPolicy> repository, ILogger<AdmissionPolicyServices> logger, ITextEmbeddingService embeddingService)
    : IAdmissionPolicyServices
{
    private readonly IRepository<AdmissionPolicy> _repository = repository;
    private readonly ILogger<AdmissionPolicyServices> _logger = logger;
    private readonly ITextEmbeddingService _embeddingService = embeddingService;

    /// <summary>
    /// 批量创建招生政策
    /// </summary>
    /// <param name="admissionPolicies">招生政策列表</param>
    /// <returns>创建结果</returns>
    public async Task<Result<string>> CreateAdmissionPoliciesAsync(
        AdmissionPolicysDto admissionPolicies
    )
    {
        var policiesToCreate = new List<AdmissionPolicy>();
        foreach (var item in admissionPolicies.AdmissionPolicys)
        {
            var embedding = _embeddingService.GetVector(item.Name + item.Content + item.Description);
            var policy = AdmissionPolicy.CreateAdmissionPolicy(item.Name, item.Content, item.Description);
            if (policy != null)
            {
                policy.Embedding = embedding;
                policiesToCreate.Add(policy);
            }
        }
        if (policiesToCreate.Count == 0)
        {
            _logger.LogWarning("批量创建招生政策失败：没有有效的政策");
            return Result<string>.Fail("没有有效的招生政策可以创建");
        }
        await _repository.CreateRangeAsync(policiesToCreate);
        _logger.LogInformation("批量创建招生政策成功，数量：{Count}", policiesToCreate.Count);
        return Result<string>.Success("创建成功");
    }

    /// <summary>
    /// 创建招生政策
    /// </summary>
    /// <param name="admissionPolicy">招生政策</param>
    /// <returns>创建结果</returns>
    public async Task<Result<string>> CreateAdmissionPolicyAsync(AdmissionPolicyDto admissionPolicy)
    {
        var embedding = _embeddingService.GetVector(admissionPolicy.Name + admissionPolicy.Content + admissionPolicy.Description);
        var policy = AdmissionPolicy.CreateAdmissionPolicy(
            admissionPolicy.Name,
            admissionPolicy.Content,
            admissionPolicy.Description
        );
        if (policy == null)
        {
            _logger.LogWarning("创建招生政策失败，参数：{@AdmissionPolicy}", admissionPolicy);
            return Result<string>.Fail("创建招生政策失败");
        }
        policy.Embedding = embedding;
        await _repository.CreateAsync(policy);
        _logger.LogInformation("创建招生政策成功，政策：{Name}", admissionPolicy.Name);
        return Result<string>.Success("创建成功");
    }

    /// <summary>
    /// 批量删除招生政策
    /// </summary>
    /// <param name="ids">招生政策ID列表</param>
    /// <returns>删除结果</returns>
    public async Task<Result<string>> DeleteAdmissionPoliciesAsync(IEnumerable<Guid> ids)
    {
        // 并行获取所有政策
        var tasks = ids.Select(id => _repository.GetByIdAsync(id));
        var policies = await Task.WhenAll(tasks);

        // 过滤掉 null 值并转换为非空类型
        var validPolicies = policies.OfType<AdmissionPolicy>().ToList();

        // 检查是否有有效的政策
        if (validPolicies.Count == 0)
        {
            _logger.LogWarning("批量删除招生政策失败：未找到任何政策，ids={@Ids}", ids);
            return Result<string>.Fail("没有找到招生政策");
        }

        // 调用 Delete 方法标记为删除
        foreach (var policy in validPolicies)
        {
            if (!policy.Delete())
            {
                _logger.LogWarning("批量删除招生政策时，政策已被删除，id={Id}", policy.Id);
                return Result<string>.Fail($"招生政策 {policy.Id} 已经被删除");
            }
        }

        // 更新所有有效的政策
        await _repository.UpdateRangeAsync(validPolicies);
        _logger.LogInformation("批量删除招生政策成功，数量：{Count}", validPolicies.Count);

        return Result<string>.Success("删除成功");
    }

    /// <summary>
    /// 删除招生政策
    /// </summary>
    /// <param name="id">招生政策ID</param>
    /// <returns>删除结果</returns>
    public async Task<Result<string>> DeleteAdmissionPolicyAsync(Guid id)
    {
        var policy = await _repository.GetByIdAsync(id);
        if (policy == null)
        {
            _logger.LogWarning("删除招生政策失败：未找到政策，id={Id}", id);
            return Result<string>.Fail("没有找到招生政策");
        }
        if (!policy.Delete())
        {
            _logger.LogWarning("删除招生政策失败：政策已被删除，id={Id}", id);
            return Result<string>.Fail("招生政策已经被删除");
        }
        await _repository.UpdateAsync(policy);
        _logger.LogInformation("删除招生政策成功，id={Id}", id);
        return Result<string>.Success("删除成功");
    }

    /// <summary>
    /// 根据ID获取招生政策
    /// </summary>
    /// <param name="id">招生政策ID</param>
    /// <returns>招生政策</returns>
    public async Task<Result<AdmissionPolicy>> GetAdmissionPolicyByIdAsync(Guid id)
    {
        var policy = await _repository.GetByIdAsync(id);
        if (policy == null)
        {
            return Result<AdmissionPolicy>.Fail("没有找到招生政策");
        }
        return Result<AdmissionPolicy>.Success(policy);
    }

    /// <summary>
    /// 获取招生政策数量
    /// </summary>
    /// <returns>招生政策数量</returns>
    public async Task<int> GetAdmissionPolicyCountAsync()
    {
        return await _repository.GetCountAsync();
    }

    /// <summary>
    /// 获取所有招生政策
    /// </summary>
    /// <returns>招生政策列表</returns>
    public async Task<Result<IEnumerable<AdmissionPolicy>>> GetAllAdmissionPoliciesAsync()
    {
        var policies = await _repository.GetAllAsync();
        return Result<IEnumerable<AdmissionPolicy>>.Success(policies);
    }

    /// <summary>
    /// 分页获取招生政策
    /// </summary>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>分页结果</returns>
    public async Task<Result<IEnumerable<AdmissionPolicy>>> GetPagedAdmissionPoliciesAsync(
        int pageIndex = 0,
        int pageSize = 10
    )
    {
        var policies = await _repository.GetPagedAsync(pageIndex, pageSize);
        return Result<IEnumerable<AdmissionPolicy>>.Success(policies);
    }

    /// <summary>
    /// 根据名称搜索招生政策
    /// </summary>
    /// <param name="policyName">政策名称</param>
    /// <returns>匹配的政策列表</returns>
    public async Task<Result<IEnumerable<AdmissionPolicy>>> SearchAdmissionPoliciesByNameAsync(
        string policyName
    )
    {
        var policies = await _repository.GetListConditionAsync(item =>
            item.AdmissionPolicyName.Contains(policyName)
        );
        return Result<IEnumerable<AdmissionPolicy>>.Success(policies);
    }

    /// <summary>
    /// 更新招生政策
    /// </summary>
    /// <param name="id">政策ID</param>
    /// <param name="admissionPolicy">招生政策</param>
    public async Task<Result<string>> UpdateAdmissionPolicyAsync(
        Guid id,
        AdmissionPolicyDto admissionPolicy
    )
    {
        var policy = await _repository.GetByIdAsync(id);
        if (policy == null)
        {
            _logger.LogWarning("更新招生政策失败：未找到政策，id={Id}", id);
            return Result<string>.Fail("没有找到招生政策");
        }
        policy.UpdateAdmissionPolicy(
            admissionPolicy.Name,
            admissionPolicy.Content,
            admissionPolicy.Description
        );
        policy.Embedding = _embeddingService.GetVector(admissionPolicy.Name + admissionPolicy.Content + admissionPolicy.Description);
        await _repository.UpdateAsync(policy);
        _logger.LogInformation("更新招生政策成功，id={Id}", id);
        return Result<string>.Success("更新成功");
    }

    /// <summary>
    /// 基于向量相似度搜索招生政策
    /// </summary>
    /// <param name="text">查询文本</param>
    /// <param name="topK">返回最相似的前K个</param>
    /// <returns>最相似的政策列表</returns>
    public async Task<Result<IEnumerable<AdmissionPolicy>>> SearchAdmissionPoliciesByEmbeddingAsync(string text, int topK = 5)
    {
        var queryEmbedding = _embeddingService.GetVector(text);
        var allPolicies = await _repository.GetAllAsync();
        var withScore = allPolicies
            .Where(p => p.Embedding != null)
            .Select(p => new
            {
                Policy = p,
                Score = CosineSimilarity(queryEmbedding, p.Embedding!)
            })
            .OrderByDescending(x => x.Score)
            .Take(topK)
            .Select(x => x.Policy)
            .ToList();
        return Result<IEnumerable<AdmissionPolicy>>.Success(withScore);
    }

    private static float CosineSimilarity(float[] v1, float[] v2)
    {
        if (v1 == null || v2 == null || v1.Length != v2.Length) return 0f;
        float dot = 0, norm1 = 0, norm2 = 0;
        for (int i = 0; i < v1.Length; i++)
        {
            dot += v1[i] * v2[i];
            norm1 += v1[i] * v1[i];
            norm2 += v2[i] * v2[i];
        }
        if (norm1 == 0 || norm2 == 0) return 0f;
        return dot / (float)(Math.Sqrt(norm1) * Math.Sqrt(norm2));
    }
}
